use dioxus::prelude::*;
use std::time::Duration;
use tokio::sync::mpsc;

mod network;
use network::{Libp2pMessaging, NetworkCommand, NetworkEvent};

#[component]
pub fn ChatRoom() -> Element {
    let mut input_value = use_signal(|| String::new());
    let mut messages = use_signal(|| Vec::<String>::new());
    let mut peers = use_signal(|| Vec::<String>::new());

    // Only store the sender in the signal
    let msg_tx = use_signal(|| {
        let (tx, _) = mpsc::channel::<NetworkCommand>(32);
        tx
    });

    use_hook(|| {
        let (ui_tx, ui_rx) = mpsc::channel::<NetworkCommand>(32); // Create new channel pair
        let (net_tx, mut net_rx) = mpsc::channel(32);

        // Update the stored sender in signal
        let mut msg_tx = msg_tx;
        msg_tx.set(ui_tx);

        // Initialize network task
        spawn(async move {
            if let Ok(mut libp2p) = Libp2pMessaging::new(ui_rx, net_tx) {
                libp2p.run().await;
            }
        });

        // Handle incoming messages from the network
        spawn(async move {
            loop {
                if let Some(event) = net_rx.recv().await {
                    match event {
                        NetworkEvent::MessageReceived(message) => {
                            messages.write().push(message);
                        }
                        NetworkEvent::PeerConnected(peer_id) => {
                            peers.write().push(peer_id);
                        }
                        NetworkEvent::PeerDisconnected(peer_id) => {
                            peers.write().retain(|id| id != &peer_id);
                        }
                    }
                }
                tokio::time::sleep(Duration::from_millis(200)).await;
            }
        });
    });

    rsx! {
        div {
            h1 { "Chat Room" }
            div {
                input {
                    value: "{input_value}",
                    oninput: move |e| input_value.set(e.value()),
                }
                button {
                    onclick: move |_| {
                        if !input_value().is_empty() {
                            let message = input_value().clone();
                            let tx = msg_tx.read().clone();
                            spawn(async move {
                                if let Err(e) = tx.send(NetworkCommand::SendMessage(message)).await {
                                    eprintln!("Failed to send message: {}", e);
                                }
                            });
                            input_value.set(String::new());
                        }
                    },
                    "Send"
                }
            }
            div {
                h2 { "Messages" }
                ul {
                    for message in messages.read().iter() {
                        li { "{message}" }
                    }
                }
            }
            div {
                h2 { "Peers" }
                ul {
                    for peer in peers.read().iter() {
                        li { "{peer}" }
                    }
                }
            }
        }
    }
}
